package com.pmcc.utils;


import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.*;


/**
 * 对象的属性复制
 * 
 * @author wp
 *
 */
public abstract class BeanUtils extends org.springframework.beans.BeanUtils {



	@SuppressWarnings("unused")
	public static String getRequestPayload(HttpServletRequest req) {
		StringBuilder sb = new StringBuilder();
		try {
			BufferedReader reader = req.getReader();
			char[] buff = new char[1024];
			int len;
			while ((len = reader.read(buff)) != -1) {
				sb.append(buff, 0, len);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		String result = sb.toString();
		if (result.startsWith("{"))
			result = '[' + result + ']';// to Array
		return result;
	}


	/**
	 * 从request中获取不为空的数据放到持久对象中
	 * @param bean
	 * @param request
	 */
	public static void setBeanData(Object bean, HttpServletRequest request){
		Class clazz = bean.getClass();
		Method ms[] = clazz.getDeclaredMethods();
		String mname;
		String field;
		String fieldType;
		
		Map map=request.getParameterMap();
	    Set keSet=map.entrySet();
	    for(Iterator itr=keSet.iterator();itr.hasNext();){
	    	String value = "";
	        Map.Entry me=(Map.Entry)itr.next();
	        Object ok=me.getKey();
	        Object ov=me.getValue();
	        String[] ovvalue=new String[1];
	        if(ov instanceof String[]){
	        	ovvalue=(String[])ov;
	        }else{
	        	ovvalue[0]=ov.toString();
	        }

	        for(int k=0;k<ovvalue.length;k++){
	        	value = ovvalue[k];
	        }
	        for(Method m : ms){
	        	mname = m.getName();
				if (!mname.startsWith("set") || ArrayUtils.isEmpty(m.getParameterTypes())) {
					continue;
				}
				try {
					field = mname.toLowerCase().charAt(3) + mname.substring(4, mname.length());
					if(ok.equals(field)){
//						if (StringUtils.isEmpty(value)) {
//							m.invoke(bean, value);
//							continue;
//						}
						fieldType = m.getParameterTypes()[0].getName();
						// 以下可以确认value为String类型
						if (String.class.getName().equals(fieldType)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (String)null);
							}else{
								m.invoke(bean, (String) value);
							}
						} else if (Integer.class.getName().equals(fieldType) && NumberUtils.isDigits((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Integer)null);
							}else{
								m.invoke(bean, Integer.valueOf((String) value));
							}
							
						} else if (Short.class.getName().equals(fieldType) && NumberUtils.isDigits((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Short)null);
							}else{
								m.invoke(bean, Short.valueOf((String) value));
							}
						} else if (Float.class.getName().equals(fieldType) && NumberUtils.isNumber((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Float)null);
							}else{
								m.invoke(bean, Float.valueOf((String) value));
							}
							
						} else if (Double.class.getName().equals(fieldType) && NumberUtils.isNumber((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Double)null);
							}else{
								m.invoke(bean, Double.valueOf((String) value));
							}
							
						} else if (Long.class.getName().equals(fieldType) && NumberUtils.isNumber((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Long)null);
							}else{
								m.invoke(bean, Long.valueOf((String) value));
							}
							
						} else if (Date.class.getName().equals(fieldType)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Date)null);
							}else{
								m.invoke(bean, DateUtils.parseDate((String) value, "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss"));
							}
							
						} else if (BigDecimal.class.getName().equals(fieldType)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (BigDecimal)null);
							}else{
								m.invoke(bean, BigDecimal.valueOf(Double.valueOf(value)));
							}
								
						} else {
							m.invoke(bean, value);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
					continue;
				}
	        }
	       
	      }
	}


	public static <T> T toBean(Class<T> clazz, Map map) {
		T obj = null;
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
			obj = clazz.newInstance(); // 创建 JavaBean 对象

			// 给 JavaBean 对象的属性赋值
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (int i = 0; i < propertyDescriptors.length; i++) {
				PropertyDescriptor descriptor = propertyDescriptors[i];
				String propertyName = descriptor.getName();
				if (map.containsKey(propertyName)) {
					// 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
					Object value = map.get(propertyName);
					if ("".equals(value)) {
						value = null;
					}
					Object[] args = new Object[1];
					args[0] = value;
					try {
						descriptor.getWriteMethod().invoke(obj, args);
					} catch (InvocationTargetException e) {
						System.out.println("字段映射失败");
					}
				}
			}
		} catch (IllegalAccessException e) {
			System.out.println("实例化 JavaBean 失败");
		} catch (IntrospectionException e) {
			System.out.println("分析类属性失败");
		} catch (IllegalArgumentException e) {
			System.out.println("映射错误");
		} catch (InstantiationException e) {
			System.out.println("实例化 JavaBean 失败");
		}
		return (T) obj;
	}



	public static void setBeanData(Object bean, Map<String,String> map){
		Class clazz = bean.getClass();
		Method ms[] = clazz.getDeclaredMethods();
		String mname;
		String field;
		String fieldType;

		Set keSet=map.entrySet();
		for(Iterator itr=keSet.iterator();itr.hasNext();){
			String value = "";
			Map.Entry me=(Map.Entry)itr.next();
			Object ok=me.getKey();
			Object ov=me.getValue();
			String[] ovvalue=new String[1];
			if(ov instanceof String[]){
				ovvalue=(String[])ov;
			}else{
				ovvalue[0]=ov.toString();
			}

			for(int k=0;k<ovvalue.length;k++){
				value = ovvalue[k];
			}
			for(Method m : ms){
				mname = m.getName();
				if (!mname.startsWith("set") || ArrayUtils.isEmpty(m.getParameterTypes())) {
					continue;
				}
				try {
					field = mname.toLowerCase().charAt(3) + mname.substring(4, mname.length());
					if(ok.equals(field)){
//						if (StringUtils.isEmpty(value)) {
//							m.invoke(bean, value);
//							continue;
//						}
						fieldType = m.getParameterTypes()[0].getName();
						// 以下可以确认value为String类型
						if (String.class.getName().equals(fieldType)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (String)null);
							}else{
								m.invoke(bean, (String) value);
							}
						} else if (Integer.class.getName().equals(fieldType) && NumberUtils.isDigits((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Integer)null);
							}else{
								m.invoke(bean, Integer.valueOf((String) value));
							}

						} else if (Short.class.getName().equals(fieldType) && NumberUtils.isDigits((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Short)null);
							}else{
								m.invoke(bean, Short.valueOf((String) value));
							}
						} else if (Float.class.getName().equals(fieldType) && NumberUtils.isNumber((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Float)null);
							}else{
								m.invoke(bean, Float.valueOf((String) value));
							}

						} else if (Double.class.getName().equals(fieldType) && NumberUtils.isNumber((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Double)null);
							}else{
								m.invoke(bean, Double.valueOf((String) value));
							}

						} else if (Long.class.getName().equals(fieldType) && NumberUtils.isNumber((String) value)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Long)null);
							}else{
								m.invoke(bean, Long.valueOf((String) value));
							}

						} else if (Date.class.getName().equals(fieldType)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (Date)null);
							}else{
								m.invoke(bean, DateUtils.parseDate((String) value, "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss"));
							}

						} else if (BigDecimal.class.getName().equals(fieldType)) {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, (BigDecimal)null);
							}else{
								m.invoke(bean, BigDecimal.valueOf(Double.valueOf(value)));
							}
						}else {
							if(StringUtils.isEmpty(value)){
								m.invoke(bean, null);
							}else{
								m.invoke(bean, value);
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
					continue;
				}
			}

		}
	}

    // Map --> Bean 1: 利用Introspector,PropertyDescriptor实现 Map --> Bean  
    public static void transMap2Bean(Map<String, Object> map, Object obj) {  
        try {  
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
  
            for (PropertyDescriptor property : propertyDescriptors) {  
                String key = property.getName();  
  
                if (map.containsKey(key)) {  
                    Object value = map.get(key);  
                    // 得到property对应的setter方法  
                    Method setter = property.getWriteMethod();  
                    setter.invoke(obj, value);  
                }  
            }  
        } catch (Exception e) {  
            System.out.println("transMap2Bean Error " + e);  
        }  
        return;  
    } 
    
    // Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map  
    public static Map<String, Object> transBean2Map(Object obj) {  
        if(obj == null){  
            return null;  
        }          
        Map<String, Object> map = new HashMap<String, Object>();  
        try {  
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
            for (PropertyDescriptor property : propertyDescriptors) {  
                String key = property.getName();  
  
                // 过滤class属性  
                if (!key.equals("class")) {  
                    // 得到property对应的getter方法  
                    Method getter = property.getReadMethod();  
                    Object value = getter.invoke(obj);  
  
                    map.put(key, value);  
                }  
            }  
        } catch (Exception e) {  
            System.out.println("transBean2Map Error " + e);  
        }  
        return map;  
    }
	// Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
	public static Map<String, Object> transBean2MapNoNull(Object obj) {
		if(obj == null){
			return null;
		}
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor property : propertyDescriptors) {
				String key = property.getName();

				// 过滤class属性
				if (!key.equals("class")) {
					// 得到property对应的getter方法
					Method getter = property.getReadMethod();
					Object value = getter.invoke(obj);
					if(value !=null){
						map.put(key, value);
					}
				}
			}
		} catch (Exception e) {
			System.out.println("transBean2Map Error " + e);
		}
		return map;
	}

}
